#pragma once

namespace GameUtilities
{
	VOID GetOriginFromMatrix(fb::LinearTransform* pMatrix, fb::Vec3* vOrigin)
	{
		memcpy(vOrigin, &(pMatrix->trans), sizeof(fb::Vec3));
	}

	void GetPosition(fb::ClientSoldierEntity* pSoldier, fb::Vec3* Out)
	{
		memcpy(Out, &(pSoldier->m_meshTransform.trans), sizeof(fb::Vec3));
	}

	bool WorldToScreen(fb::Vec3* In, fb::Vec3* Out)
	{
		/*if( MyGameRenderer->m_viewParams.view.Update() == FALSE )
		{
			return false;
		}*/

		JUNK_CODE;
		float CX = static_cast< float >( MyDxRenderer->m_screenInfo.m_nWindowWidth ) * 0.5f;
		JUNK_CODE;
		float CY = static_cast< float >( MyDxRenderer->m_screenInfo.m_nWindowHeight ) * 0.5f;

		fb::LinearTransform ScreenTransform = fb::GameRenderer::Singleton()->m_viewParams.view.m_viewProjectionMatrix;

		JUNK_CODE;
		fb::Vec3 Origin = ( *In );

		float W = 
			ScreenTransform.m_rows[0].w * Origin.x +
			ScreenTransform.m_rows[1].w * Origin.y +
			ScreenTransform.m_rows[2].w * Origin.z +
			ScreenTransform.m_rows[3].w;

		JUNK_CODE;
		if( W < 0.0001f )
		{
			Out->z = W;
			return false;
		}

		JUNK_CODE;
		float X = 
			ScreenTransform.m_rows[0].x * Origin.x +
			ScreenTransform.m_rows[1].x * Origin.y +
			ScreenTransform.m_rows[2].x * Origin.z + 
			ScreenTransform.m_rows[3].x;

		JUNK_CODE;
		float Y = 
			ScreenTransform.m_rows[0].y * Origin.x +
			ScreenTransform.m_rows[1].y * Origin.y +
			ScreenTransform.m_rows[2].y * Origin.z + 
			ScreenTransform.m_rows[3].y;

		Out->x = CX + CX * X / W;
		JUNK_CODE;
		Out->y = CY - CY * Y / W;
		JUNK_CODE;
		Out->z = W;

		return true;
	}  

	float GetDistance(fb::Vec3* v1,fb::Vec3* v2)
	{
		return sqrt( ((v1->x-v2->x)*(v1->x-v2->x)) + ((v1->y-v2->y)*(v1->y-v2->y)) + ((v1->z-v2->z)*(v1->z-v2->z)));
	}

	bool GetBonePos(fb::ClientSoldierEntity* pSoldier, fb::Vec3* vecout, int bone)
	{
		fb::ClientAntAnimatableComponent* MyAntComp = pSoldier->m_animatableComponent[1];
		if (MyAntComp)
		{
			JUNK_CODE;
			MyAntComp->m_hadVisualUpdate = true;
		}
		fb::BoneCollisionComponent* pBCC = pSoldier->m_boneCollisionComponent;
		JUNK_CODE;
		if (!pBCC)
		{
			return false;
		}
		*vecout = pBCC->m_boneCollisionTransforms[bone].transform.trans;
		JUNK_CODE;
		fb::Vec3 tmp;
		GetPosition(pSoldier, &tmp);
		return (GetDistance(vecout, &tmp) < 3.0f);
	}

	fb::ClientSoldierWeapon* GetCurrentWeapon(fb::ClientSoldierEntity* pSoldier)
	{
		if(pSoldier->m_soldierWeaponsComponent)
		{
			JUNK_CODE;
			if(pSoldier->m_soldierWeaponsComponent->m_currentAnimatedWeaponHandler)
			{
				JUNK_CODE;
				return pSoldier->m_soldierWeaponsComponent->m_currentAnimatedWeaponHandler->m_currentAnimatedWeapon;
			}
		}
		JUNK_CODE;
		return NULL;
	}

	bool IsVisible(fb::Vec3* Origin, fb::Vec3* target)
	{
		if(!MyGameContext->m_level || !MyGameContext->m_level->hkPhysicsManager)
		{
			JUNK_CODE;
			return false;
		}
		JUNK_CODE;
		fb::IPhysicsRayCaster* pRC = MyGameContext->m_level->hkPhysicsManager->m_rayCaster;
		if(!pRC)
		{
			return false;
		}

		JUNK_CODE;
		fb::RayCastHit ray;
		__declspec(align(16)) fb::Vec3 from = *Origin;
		JUNK_CODE;
		__declspec(align(16)) fb::Vec3 to = *target;
		JUNK_CODE;
		return !pRC->physicsRayQuery(/*x*/ SD_Tools::CryptStringA(1, 0xCEF, 0x3A000000).c_str(), &from, &to, &ray, 0x4 | 0x10 | 0x20 | 0x80, NULL);
	}
}

